// CODE39.js - 已改为 ES Module 格式，兼容 UniApp
import Barcode from "../Barcode.js"; // 确保路径正确，且 Barcode.js 是 ES Module 版本

// 所有字符定义。数组下标即为其校验值
const characters = [
  "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
  "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
  "-", ".", " ", "$", "/", "+", "%", "*"
];

// 字符对应的十进制编码（用于转为二进制）
const encodings = [
  20957, 29783, 23639, 30485, 20951, 29813, 23669, 20855, 29789, 23645,
  29975, 23831, 30533, 22295, 30149, 24005, 21623, 29981, 23837, 22301,
  30023, 23879, 30545, 22343, 30161, 24017, 21959, 30065, 23921, 22385,
  29015, 18263, 29141, 17879, 29045, 18293, 17783, 29021, 18269, 17477,
  17489, 17681, 20753, 35770
];

// 获取字符的二进制编码（如 "A" -> "10101100101"）
function getEncoding(character) {
  return getBinary(characterValue(character));
}

// 将十进制编码转为二进制字符串
function getBinary(characterValue) {
  return encodings[characterValue].toString(2);
}

// 获取字符在字符表中的索引（即校验值）
function characterValue(character) {
  const index = characters.indexOf(character.toUpperCase());
  if (index === -1) {
    throw new Error(`CODE39 错误：不支持的字符 "${character}"`);
  }
  return index;
}

// 计算 mod43 校验码
function mod43checksum(data) {
  let checksum = 0;
  for (let i = 0; i < data.length; i++) {
    checksum += characterValue(data[i]);
  }
  return checksum % 43;
}

// CODE39 编码器类
export class CODE39 extends Barcode {
  constructor(data, options) {
    // 转为大写
    data = data.toUpperCase();

    // 如果启用 mod43 校验，自动添加校验字符
    if (options.mod43) {
      data += getCharacter(mod43checksum(data));
    }

    super(data, options);

    // 显示文本去掉起止符 *（如果设置了自定义文本则保留）
    this.text = this.options.text || this.data;
  }

  // 编码生成二进制字符串
  encode() {
    let result = getEncoding("*"); // 起始符 *

    for (let i = 0; i < this.data.length; i++) {
      result += getEncoding(this.data[i]) + "0"; // 每个字符后加窄空格 "0"
    }

    result += getEncoding("*"); // 结束符 *

    return {
      data: result,
      text: this.text
    };
  }

  // 验证数据是否合法
  valid() {
    return /^[0-9A-Z\-\.\ \$\/\+\%]+$/.test(this.data);
  }
}

// 辅助函数：根据校验值获取字符
function getCharacter(value) {
  return characters[value];
}
